package com.system.file.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.system.core.utils.BizAssert;
import com.system.core.utils.DateUtils;
import com.system.file.common.domain.FileAttrDO;
import com.system.file.common.domain.FileStatisticsDO;
import com.system.file.common.dto.FileOverviewDTO;
import com.system.file.common.dto.FileStatisticsAllDTO;
import com.system.file.common.dto.FolderDTO;
import com.system.file.common.dto.FolderSaveDTO;
import com.system.file.common.entity.File;
import com.system.file.common.enumeration.DataType;
import com.system.file.common.enumeration.IconType;
import com.system.file.mapper.FileMapper;
import com.system.file.service.FileService;
import com.system.file.strategy.FileStrategy;
import com.system.file.utils.DozerUtils;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.validator.constraints.ScriptAssert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;


import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.List;

import static com.system.core.exception.code.ExceptionCode.BASE_VALID_PARAM;
import static com.system.core.utils.StrPool.DEF_PARENT_ID;
import static com.system.core.utils.StrPool.DEF_ROOT_PATH;

@Service
public class FileServiceImpl extends ServiceImpl<FileMapper, File> implements FileService {

    @Autowired
    private FileStrategy fileStrategy;

    @Autowired
    private DozerUtils dozerUtils;

    @Autowired
    private FileMapper fileMapper;

    @Override
    public FolderDTO saveFolder(FolderSaveDTO folderSaveDto) {
        File folder = dozerUtils.map2(folderSaveDto, File.class);
        if (folderSaveDto.getFolderId() == null || folderSaveDto.getFolderId() <= 0) {
            folder.setFolderId(DEF_PARENT_ID);
            folder.setTreePath(DEF_ROOT_PATH);
            folder.setGrade(1);
        } else {
            File parent = super.getById(folderSaveDto.getFolderId());
            BizAssert.notNull(parent, BASE_VALID_PARAM.build("父文件夹不能为空"));
            BizAssert.isFalse(parent.getIsDelete(), BASE_VALID_PARAM.build("父文件夹已经被删除"));
            BizAssert.equals(DataType.DIR.name(), parent.getDataType().name(), BASE_VALID_PARAM.build("父文件夹不存在"));
            BizAssert.isTrue(parent.getGrade() < 10, BASE_VALID_PARAM.build("文件夹层级不能超过10层"));
            folder.setFolderName(parent.getSubmittedFileName());
            folder.setTreePath(StringUtils.join(parent.getTreePath(), parent.getId(), DEF_ROOT_PATH));
            folder.setGrade(parent.getGrade() + 1);
        }
        if (folderSaveDto.getOrderNum() == null) {
            folderSaveDto.setOrderNum(0);
        }
        folder.setIsDelete(false);
        folder.setDataType(DataType.DIR);
        folder.setIcon(IconType.DIR.getIcon());
        setDate(folder);
        fileMapper.insert(folder);
        return dozerUtils.map2(folder, FolderDTO.class);
    }

    @Override
    public void download(HttpServletRequest request, HttpServletResponse response, Long[] ids, Long userId) throws Exception {

    }

    @Override
    public Boolean removeList(Long userId, Long[] ids) {
        return null;
    }

    @Override
    public FileAttrDO getFileAttrDo(Long folderId) {
        String treePath = DEF_ROOT_PATH;
        String folderName = "";
        Integer grade = 1;
        if (folderId == null || folderId <= 0) {
            return new FileAttrDO(treePath, grade, folderName, DEF_PARENT_ID);
        }
        File folder = this.getById(folderId);

        if (folder != null && !folder.getIsDelete() && DataType.DIR.eq(folder.getDataType())) {
            folderName = folder.getSubmittedFileName();
            treePath = StringUtils.join(folder.getTreePath(), folder.getId(), DEF_ROOT_PATH);
            grade = folder.getGrade() + 1;
        }
        BizAssert.isTrue(grade <= 10, BASE_VALID_PARAM.build("文件夹层级不能超过10层"));
        return new FileAttrDO(treePath, grade, folderName, folderId);
    }

    @Override
    public File upload(MultipartFile simpleFile, Long folderId) {
        FileAttrDO fileAttrDO = this.getFileAttrDo(folderId);
        String treePath = fileAttrDO.getTreePath();
        String folderName = fileAttrDO.getFolderName();
        Integer grade = fileAttrDO.getGrade();

        File file = fileStrategy.upload(simpleFile);
        file.setFolderId(folderId);
        file.setFolderName(folderName);
        file.setGrade(grade);
        file.setTreePath(treePath);
        super.save(file);
        return file;
    }

    @Override
    public File upload(MultipartFile simpleFile, Long folderId, String source, Long userId) {
        FileAttrDO fileAttrDO = this.getFileAttrDo(folderId);
        String treePath = fileAttrDO.getTreePath();
        String folderName = fileAttrDO.getFolderName();
        Integer grade = fileAttrDO.getGrade();

        File file = fileStrategy.upload(simpleFile);
        file.setFolderId(folderId);
        file.setFolderName(folderName);
        file.setGrade(grade);
        file.setTreePath(treePath);
        super.save(file);
        return file;
    }

    @Override
    public FileOverviewDTO findOverview(Long userId, LocalDateTime startTime, LocalDateTime endTime) {
        return null;
    }

    @Override
    public FileStatisticsAllDTO findAllByDate(Long userId, LocalDateTime startTime, LocalDateTime endTime) {
        return null;
    }

    @Override
    public List<FileStatisticsDO> findAllByDataType(Long userId) {
        return null;
    }

    @Override
    public List<FileStatisticsDO> downTop20(Long userId) {
        return null;
    }

    @Override
    public FileStatisticsAllDTO findNumAndSizeToTypeByDate(Long userId, LocalDateTime startTime, LocalDateTime endTime) {
        return null;
    }

    @Override
    public FileStatisticsAllDTO findDownSizeByDate(Long userId, LocalDateTime startTime, LocalDateTime endTime) {
        return null;
    }

    private void setDate(File file) {
        LocalDateTime now = LocalDateTime.now();
        file.setCreateMonth(DateUtils.formatAsYearMonthEn(now))
                .setCreateWeek(DateUtils.formatAsYearWeekEn(now))
                .setCreateDay(DateUtils.formatAsDateEn(now));
    }
}
